---
title: "Button"
description: "Buttons allow users to perform actions and choose with a single tap."
---

import {buttonContent} from "@/content/components/button";

# Button

Buttons allow users to perform actions and choose with a single tap.

<ComponentLinks component="button" reactAriaHook="useButton" />

---

<CarbonAd />

## Installation

<PackageManagers
  showGlobalInstallWarning
  commands={{
    cli: "npx heroui-cli@latest add button",
    npm: "npm install @heroui/button",
    yarn: "yarn add @heroui/button",
    pnpm: "pnpm add @heroui/button",
    bun: "bun add @heroui/button",
  }}
/>

## Import

HeroUI exports 2 button-related components:

- **Button**: The main component to display a button.
- **ButtonGroup**: A wrapper component to display a group of buttons.

<ImportTabs
  commands={{
    main: 'import {Button, ButtonGroup} from "@heroui/react";',
    individual: 'import {Button, ButtonGroup} from "@heroui/button";',
  }}
/>

## Usage

<CodeDemo title="Usage" files={buttonContent.usage} />

### Disabled

<CodeDemo title="Disabled" files={buttonContent.disabled} />

### Sizes

<CodeDemo title="Sizes" files={buttonContent.sizes} />

### Radius

<CodeDemo title="Radius" files={buttonContent.radius} />

### Colors

<CodeDemo title="Colors" files={buttonContent.colors} />

### Variants

<CodeDemo title="Variants" files={buttonContent.variants} />

### Loading

Pass the `isLoading` prop to display a [Spinner](/docs/components/spinner) component inside the button.

<CodeDemo title="Loading" files={buttonContent.loading} />

You can also customize the loading spinner by passing the a custom component to the `spinner` prop.

<CodeDemo title="Custom Loading" files={buttonContent.loadingCustom} />

### With Icons

You can add icons to the `Button` by passing the `startContent` or `endContent` props.

<CodeDemo title="With Icons" files={buttonContent.icons} />

### Icon Only

You can also display a button without text by passing the `isIconOnly` prop and the desired icon as `children`.

<CodeDemo title="With Icons" files={buttonContent.iconOnly} />

### Custom Styles

You can customize the `Button` component by passing custom Tailwind CSS classes to the component slots.

<CodeDemo title="Custom Styles" files={buttonContent.customStyles} />

> Custom class names will override the default ones thanks to [Tailwind Merge](https://github.com/dcastil/tailwind-merge) library. It
> means that you don't need to worry about class conflicts.

### Custom Implementation

You can also use the `useButton` hook to create your own button component.

<CodeDemo
  showPreview={false}
  showOpenInCodeSandbox={false}
  title="Custom Implementation"
  files={buttonContent.customImpl}
/>

## Button Group

<CodeDemo title="Button Group" files={buttonContent.group} />

### Group Disabled

The `ButtonGroup` component also accepts the `isDisabled` prop to disable all buttons inside it.

<CodeDemo title="Group Disabled" files={buttonContent.groupDisabled} />

### Group Use case

A common use case for the `ButtonGroup` component is to display a group of two buttons one for the selected value and another for the `dropdown`.

<CodeDemo title="Group Use case" files={buttonContent.groupUseCase} />

> See the [Dropdown](/docs/components/dropdown) component for more details.

<Spacer y={4} />

## Data Attributes

`Button` has the following attributes on the `base` element:

- **data-hover**:
  When the button is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
- **data-focus**:
  When the button is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-focus-visible**:
  When the button is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-disabled**:
  When the button is disabled. Based on `isDisabled` prop.
- **data-pressed**:
  When the button is pressed. Based on [usePress](https://react-spectrum.adobe.com/react-aria/usePress.html)
- **data-loading**:
  When the button is loading. Based on `isLoading` prop.

<Spacer y={4} />

## Accessibility

- Button has role of `button`.
- Keyboard event support for <Kbd>Space</Kbd> and <Kbd>Enter</Kbd> keys.
- Mouse and touch event handling, and press state management.
- Keyboard focus management and cross browser normalization.

We recommend to read this [blog post](https://react-spectrum.adobe.com/blog/building-a-button-part-1.html) about the complexities of
building buttons that work well across devices and interaction methods.

<Spacer y={4} />

## API

### Button Props

<APITable
  data={[
    {
      attribute: "children",
      type: "ReactNode",
      description: "The content to display in the button.",
      default: "-"
    },
    {
      attribute: "variant",
      type: 'solid | bordered | light | flat | faded | shadow | ghost',
      description: "The button appearance style.",
      default: "solid"
    },
    {
      attribute: "color",
      type: "default | primary | secondary | success | warning | danger",
      description: "The button color theme.",
      default: "default"
    },
    {
      attribute: "size",
      type: "sm | md | lg",
      description: "The button size.",
      default: "md"
    },
    {
      attribute: "radius",
      type: "none | sm | md | lg | full",
      description: "The button border radius.",
      default: "-"
    },
    {
      attribute: "startContent",
      type: "ReactNode",
      description: "The button start content.",
      default: "-"
    },
    {
      attribute: "endContent",
      type: "ReactNode",
      description: "The button end content.",
      default: "-"
    },
    {
      attribute: "spinner",
      type: "ReactNode",
      description: "Spinner to display when loading.",
      default: "-"
    },
    {
      attribute: "spinnerPlacement",
      type: "start | end",
      description: "The spinner placement.",
      default: "start"
    },
    {
      attribute: "fullWidth",
      type: "boolean",
      description: "Whether the button should take the full width of its parent.",
      default: "false"
    },
    {
      attribute: "isIconOnly",
      type: "boolean",
      description: "Whether the button should have the same width and height.",
      default: "false"
    },
    {
      attribute: "isDisabled",
      type: "boolean",
      description: "Whether the button is disabled.",
      default: "false"
    },
    {
      attribute: "isLoading",
      type: "boolean",
      description: "Whether the button is loading.",
      default: "false"
    },
    {
      attribute: "disableRipple",
      type: "boolean",
      description: "Whether the button should display a ripple effect on press.",
      default: "false"
    },
    {
      attribute: "disableAnimation",
      type: "boolean",
      description: "Whether the button should display animations.",
      default: "false"
    }
  ]}
/>

### Button Events

<APITable
  data={[
    {
      attribute: "onPress",
      type: "(e: PressEvent) => void",
      description: "Handler called when the press is released over the target.",
      default: "-"
    },
    {
      attribute: "onPressStart",
      type: "(e: PressEvent) => void",
      description: "Handler called when a press interaction starts.",
      default: "-"
    },
    {
      attribute: "onPressEnd",
      type: "(e: PressEvent) => void",
      description: "Handler called when a press interaction ends, either over the target or when the pointer leaves the target.",
      default: "-"
    },
    {
      attribute: "onPressChange",
      type: "(isPressed: boolean) => void",
      description: "Handler called when the press state changes.",
      default: "-"
    },
    {
      attribute: "onPressUp",
      type: "(e: PressEvent) => void",
      description: "Handler called when a press is released over the target, regardless of whether it started on the target or not.",
      default: "-"
    },
    {
      attribute: "onKeyDown",
      type: "(e: KeyboardEvent) => void",
      description: "Handler called when a key is pressed.",
      default: "-"
    },
    {
      attribute: "onKeyUp",
      type: "(e: KeyboardEvent) => void",
      description: "Handler called when a key is released.",
      default: "-"
    },
    {
      attribute: "onClick",
      deprecated: true,
      type: "MouseEventHandler",
      description: "The native button click event handler (Deprecated) use onPress instead.",
      default: "-"
    }
  ]}
/>

### Button Group Props

<APITable
  data={[
    {
      attribute: "children",
      type: "ReactNode | ReactNode[]",
      description: "The buttons to display.",
      default: "-"
    },
    {
      attribute: "variant",
      type: "solid | bordered | light | flat | faded | shadow | ghost",
      description: "The buttons appearance style.",
      default: "solid"
    },
    {
      attribute: "color",
      type: "default | primary | secondary | success | warning | danger",
      description: "The buttons color theme.",
      default: "default"
    },
    {
      attribute: "size",
      type: "sm | md | lg",
      description: "The buttons size.",
      default: "md"
    },
    {
      attribute: "radius",
      type: "none | sm | md | lg | full",
      description: "The buttons border radius.",
      default: "xl"
    },
    {
      attribute: "fullWidth",
      type: "boolean",
      description: "Whether the buttons should take the full width.",
      default: "false"
    },
    {
      attribute: "isDisabled",
      type: "boolean",
      description: "Whether the buttons are disabled.",
      default: "false"
    }
  ]}
/>
